﻿using System.Text;
using System.Text.RegularExpressions;
using ComHlp.ContentClasses;
using ComHlp.ContentClasses.VirtualControls.PlanBoard;

namespace ComHlp.Classes.Parser.Supplementary
{
    internal class PlanBoardParser
    {
        internal int ParsePlanBoard(StringBuilder sbRecvStr, MapGraphics mapGraphics, int elementLength)
        {
            //"1010101012015102920160224118003003 PR001105001000001000001VP 00002Z00 PF001036001089092089092VP 00003Z00   000582002117118117118KS 00000Z03X"
            /*
             * 1318JB0025180003N10B10 00              0008  003021010030001000017191719  RG   1  003383010080002171919221922  RGR  N  002985010030003192236403640  YGY  N  003383010030004364053595359  RG   N  003383010081005535955625562  RGR  N  003383010040006556257655765  RGR  N  003113010040007576595889588  YGR  N  003333220080008958899999999  YGR  N01  002071010100009000000050062  RRG  N011255000000000255000000000255255255000255000255000255255255128128128255128128128255255255216240210130081000006.062000014:172116118:001303607.062303600:002491006:002678512:002866018:00D/5100/1  10HT-FAERBER05/300/3  10HASPELKUFE05/300/44 10HASPELKUFET000000000RZNPF006130,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00; 00051TEXT05801550013021500001Y000  Area            00051TEXT05802090013026900001Y000  Tag
             * lfdnr    1
             * raster   3
             * ymax     18
             * init     J
             * revision B
             * xmax     00
             * xlfd     25
             * yraster  18
             * obsolet  00
             * yanz     03
             * 3*maschinfo
             *  mtyp    N10
             *  mtyp    B10
             *  mtyp     00
             * selmasch [              ]
             * yanz==3->3* anzahl auftraege
             *  m01     00
             *  m02     08
             * auftragstab start
             *  auftrag [  003021010]
             *  rgb     03
             *  start-ruest 0001
             *  start-work  0000
             *  end-work    1719
             *  umrandung  [ ]
             *  ampel      [ RG]
             *  reserver   [  ]
             *  textinfo   [ ]
             *  1  003383010080002171919221922  RGR  N  002985010030003192236403640  YGY  N  003383010030004364053595359  RG   N  003383010081005535955625562  RGR  N  003383010040006556257655765  RGR  N  003113010040007576595889588  YGR  N  003333220080008958899999999  YGR  N01  002071010100009000000050062  RRG  N011255000000000255000000000255255255000255000255000255255255128128128255128128128255255255216240210130081000006.062000014:172116118:001303607.062303600:002491006:002678512:002866018:00D/5100/1  10HT-FAERBER05/300/3  10HASPELKUFE05/300/44 10HASPELKUFET000000000RZNPF006130,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00; 00051TEXT05801550013021500001Y000  Area            00051TEXT05802090013026900001Y000  Tag
             */
            ParsedPlanBoard plainParsedPlanBoard = new ParsedPlanBoard();
            plainParsedPlanBoard.No = ParseHelper.String2Int(sbRecvStr.ToString(0, 1));
            plainParsedPlanBoard.Raster = ParsePlanBoardRaster(sbRecvStr[1]);
            plainParsedPlanBoard.YMax = ParseHelper.String2Int(sbRecvStr.ToString(2, 2));
            plainParsedPlanBoard.InitTextBuffer = sbRecvStr[4] == 'J';
            plainParsedPlanBoard.Revision = sbRecvStr[5];
            plainParsedPlanBoard.XMaxPageNo = ParseHelper.String2Int(sbRecvStr.ToString(6, 2));
            plainParsedPlanBoard.XCurrentPageNo = ParseHelper.String2Int(sbRecvStr.ToString(8, 2));
            plainParsedPlanBoard.YRaster = ParseHelper.String2Int(sbRecvStr.ToString(10, 2));
            // obsolete 2 chars
            plainParsedPlanBoard.YCount = ParseHelper.String2Int(sbRecvStr.ToString(14, 2));
            sbRecvStr.Remove(0, 16);
            elementLength -= 16;

            // 3 times machine info
            int machineInfoTypeLength = -1, machineInfoDescriptionLength = -1, machineInfoMachineNumberLength = -1;
            for (int i = 0; i < 3; i++)
            {
                switch (sbRecvStr[0])
                {
                    case 'T':
                        machineInfoTypeLength = ParseHelper.String2Int(sbRecvStr.ToString(0, 2));
                        break;
                    case 'B':
                        machineInfoDescriptionLength = ParseHelper.String2Int(sbRecvStr.ToString(0, 2));
                        break;
                    case 'N':
                        machineInfoMachineNumberLength = ParseHelper.String2Int(sbRecvStr.ToString(0, 2));
                        break;
                }

                sbRecvStr.Remove(0, 3);
                elementLength -= 3;
            }

            plainParsedPlanBoard.SelectedOrder = sbRecvStr.ToString(0, 14);
            sbRecvStr.Remove(0, 14);
            elementLength -= 14;

            // orders table - until y-anz times
            for (int i = 0; i < plainParsedPlanBoard.YCount; i++)
            {
                int ordersCountPerMachine = ParseHelper.String2Int(sbRecvStr.ToString(0, 2));
                sbRecvStr.Remove(0, 2);
                elementLength -= 2;

                for (int j = 0; j < ordersCountPerMachine; j++)
                {
                    ItxPlanBoardOrder planBoardOrder = new ItxPlanBoardOrder();
                    planBoardOrder.Order = sbRecvStr.ToString(0, 11);
                    planBoardOrder.RgbTableIndex = ParseHelper.String2Int(sbRecvStr.ToString(11, 3));
                    planBoardOrder.ZeroDifference = ParseHelper.String2Int(sbRecvStr.ToString(14, 4));
                    planBoardOrder.StartWorkDifference = ParseHelper.String2Int(sbRecvStr.ToString(18, 4));
                    planBoardOrder.EndWorkDifference = ParseHelper.String2Int(sbRecvStr.ToString(22, 4));
                    // 22+4=26 - start R auf 33?? 33-26=5 chars lost = 4 chars weg due to inprocess
                    //4 chars???
                    planBoardOrder.InProcess = sbRecvStr[30] == 'J';
                    switch (sbRecvStr[31])
                    {
                        case 'R':
                            planBoardOrder.BorderColor = EPlanBoardColor.RedSelectedOrder;
                            break;
                        case 'G':
                            planBoardOrder.BorderColor = EPlanBoardColor.GreenWorkingOrder;
                            break;
                        case 'Y':
                            planBoardOrder.BorderColor = EPlanBoardColor.YellowPrePlanning;
                            break;
                    }
                    planBoardOrder.TrafficLight = sbRecvStr.ToString(32, 3);
                    // skip 2 - reserver
                    planBoardOrder.TextInfo = sbRecvStr[37];
                    sbRecvStr.Remove(0, 37);
                }
            }

            // now we get the rgb table - at first the rgb count
            int rgbCount = ParseHelper.String2Int(sbRecvStr.ToString(0, 3));
            sbRecvStr.Remove(0, 3);
            for (int i = 0; i < rgbCount; i++)
            {
                plainParsedPlanBoard.RgbColors.Add(sbRecvStr.ToString(0, 9));
                sbRecvStr.Remove(0, 9);
            }

            // date table - we need to get special length
            int dateCount = ParseDateTableLength(sbRecvStr.ToString(0, 2));
            sbRecvStr.Remove(0, 2);
            for (int i = 0; i < dateCount; i++)
            {
                plainParsedPlanBoard.Dates.Add(sbRecvStr.ToString(0, 10));
                sbRecvStr.Remove(0, 10);
            }

            // machine table
            for (int i = 0; i < plainParsedPlanBoard.YCount; i++)
            {
                ItxPlanBoardMachine machine = new ItxPlanBoardMachine();

                // at first - we receive the machine with length of 10
                if (machineInfoMachineNumberLength != -1)
                {
                    machine.Machine = sbRecvStr.ToString(0, 10);
                    sbRecvStr.Remove(0, 10);
                }

                // now the description 
                if (machineInfoDescriptionLength != -1)
                {
                    int descLength = ParseHelper.String2Int(sbRecvStr.ToString(0, 2));
                    machine.Description = sbRecvStr.ToString(2, descLength);
                    sbRecvStr.Remove(0, descLength + 2);
                }

                // now the type
                if (machineInfoTypeLength != -1)
                {
                    machine.Type = sbRecvStr.ToString(0, 8);
                    sbRecvStr.Remove(0, 8);
                }

                plainParsedPlanBoard.Machines.Add(machine);
            }

            // check for AT texts: AT0948  005081003070 N 0 5081/3 59,40kg3000.151 001 0/49P 000622000040 N 0 P/622/0 358,17kg225160 0901 0/48  005521003030 N 0 5521/3 80,00kg3000.151 001 0/48  005521004030 N 0 5521/4 50,00kg3000.151 001 0/48  005661005030 N 0 5661/5 57,00kg3000.151 001 0/49  005741002030 N 0 5741/2 575,00kg3000.151 001 0/45P 000002000010 N 0 P/2/0 759,33kg7875 4010 0/49  005080001030 N 0 5080/1 118,80kg3000.151 001 0/52  001799010100 N 0 1799/10 637,57kgARNDT-TUFT 100 0/
            if (sbRecvStr.ToString(0, 2) == "AT")
            {
                int count = ParseHelper.String2Int(sbRecvStr.ToString(2, 2));
                sbRecvStr.Remove(0, 4);

                int offSet = 0;
                for (int i = 0; i < count; i++)
                {
                    int textLength = ParseHelper.String2Int(sbRecvStr.ToString(offSet, 2));
                    offSet = offSet + 2;

                    string ordersText = sbRecvStr.ToString(2, textLength);
                    offSet = offSet + textLength;
                    plainParsedPlanBoard.OrderTexts.Add(ordersText);
                }
                sbRecvStr.Remove(0, offSet);
            }

            // now day 0 difference: T000000000
            if (sbRecvStr.ToString(0, 2) == "T0")
            {
                plainParsedPlanBoard.Day0Diff = ParseHelper.String2Int(sbRecvStr.ToString(2, 4));
                // 4 chars not used anymore
                sbRecvStr.Remove(0, 10);
            }
            // bounds: SC0072000043330000433300004333000043330000433300004333000043330000433300004333
            if (sbRecvStr.ToString(0, 2) == "SC")
            {
                int length = ParseHelper.String2Int(sbRecvStr.ToString(2, 4));
                sbRecvStr.Remove(0, 6);
                while (length > 0)
                {
                    ItxPlanBoardBounds bounds = new ItxPlanBoardBounds();
                    //bounds.BoundsArea = sbRecvStr.ToString(0, 2);
                    bounds.StartDiff = ParseHelper.String2Int(sbRecvStr.ToString(0, 4));
                    bounds.EndDiff = ParseHelper.String2Int(sbRecvStr.ToString(4, 4));
                    sbRecvStr.Remove(0, 8);
                    length = length - 8;
                    plainParsedPlanBoard.PlanningBounds.Add(bounds);
                }
            }
            // RZN or RZJ
            if (sbRecvStr.ToString(0, 2) == "RZ")
            {
                plainParsedPlanBoard.SubmitWithoutRuestzeiten = sbRecvStr[2] == 'N';
                sbRecvStr.Remove(0, 3);
            }
            // FN
            if (sbRecvStr.ToString(0, 2) == "FN")
            {
                plainParsedPlanBoard.SuppressFinishedOrders = true;
                sbRecvStr.Remove(0, 2);
            }
            //PF006130,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00;0,00; 
            if (sbRecvStr.ToString(0, 2) == "PF")
            {
                int length = ParseHelper.String2Int(sbRecvStr.ToString(2, 4));
                //planBoard.HrFactorRaster = sbRecvStr.ToString(6, 1);
                plainParsedPlanBoard.HrFactorRaster = ParsePlanBoardRaster(sbRecvStr[6]);
                plainParsedPlanBoard.HrFactorTable = sbRecvStr.ToString(7, length);
                sbRecvStr.Remove(0, length + 7);//2=pf,4=len,factor=1,length=table
            }

            //3L005300900000000000000000000000000000000000000000000000000000
            if (sbRecvStr.ToString(0, 2) == "3L")
            {
                int complTextLength = ParseHelper.String2Int(sbRecvStr.ToString(2, 4));
                int ordersInDisplay = ParseHelper.String2Int(sbRecvStr.ToString(6, 3));
                sbRecvStr.Remove(0, 9);

                int offSet = 0;
                for (int i = 0; i < ordersInDisplay; i++)
                {
                    int textLength = ParseHelper.String2Int(sbRecvStr.ToString(offSet, 2));
                    offSet = offSet + 2;

                    plainParsedPlanBoard.Line3OrderTexts.Add(sbRecvStr.ToString(2, textLength));
                    offSet = offSet + textLength;
                }

                sbRecvStr.Remove(0, complTextLength);
            }
            // AP009090 3021 10090 3383 10090 2985 10090 3383 10090 3383 10090 3383 10090 3113 10100 3333 220090 2071 10
            if (sbRecvStr.ToString(0, 2) == "AP")
            {
                int count = ParseHelper.String2Int(sbRecvStr.ToString(2, 3));
                sbRecvStr.Remove(0, 5);
                for (int i = 0; i < count; i++)
                {
                    int textLength = ParseHelper.String2Int(sbRecvStr.ToString(0, 2));
                    plainParsedPlanBoard.OrderPlusTexts.Add(sbRecvStr.ToString(0, textLength));
                    sbRecvStr.Remove(0, textLength + 2);
                }
            }

            mapGraphics.PlainParsedPlanBoard = plainParsedPlanBoard;
            return elementLength;
        }

        /// <summary> parse special table length </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        private int ParseDateTableLength(string length)
        {
            if (!Regex.IsMatch(length, "\\A[A-Z]"))
                return ParseHelper.String2Int(length);

            int multiplier = 0;
            switch (length[0])
            {
                case 'A':
                    multiplier = 10;
                    break;
                case 'B':
                    multiplier = 11;
                    break;
                case 'C':
                    multiplier = 12;
                    break;
                case 'D':
                    multiplier = 13;
                    break;
                case 'E':
                    multiplier = 14;
                    break;
                case 'F':
                    multiplier = 15;
                    break;
                case 'G':
                    multiplier = 16;
                    break;
                case 'H':
                    multiplier = 17;
                    break;
                case 'I':
                    multiplier = 18;
                    break;
                case 'J':
                    multiplier = 19;
                    break;
                case 'K':
                    multiplier = 20;
                    break;
                case 'L':
                    multiplier = 21;
                    break;
                case 'M':
                    multiplier = 22;
                    break;
                case 'N':
                    multiplier = 23;
                    break;
                case 'O':
                    multiplier = 24;
                    break;
                case 'P':
                    multiplier = 25;
                    break;
                case 'Q':
                    multiplier = 26;
                    break;
                case 'R':
                    multiplier = 27;
                    break;
                case 'S':
                    multiplier = 28;
                    break;
                case 'T':
                    multiplier = 29;
                    break;
                case 'U':
                    multiplier = 30;
                    break;
                case 'V':
                    multiplier = 31;
                    break;
                case 'W':
                    multiplier = 32;
                    break;
                case 'X':
                    multiplier = 33;
                    break;
                case 'Y':
                    multiplier = 34;
                    break;
                case 'Z':
                    multiplier = 35;
                    break;
            }

            int baseInt = ParseHelper.String2Int(length.Substring(1, 1));
            return multiplier * baseInt;
        }

        private EPlanBoardRaster ParsePlanBoardRaster(char rasterAsChar)
        {
            switch (rasterAsChar)
            {
                default:
                    //case '1':
                    return EPlanBoardRaster.Hours2;
                case '2':
                    return EPlanBoardRaster.Hours8;
                case '3':
                    return EPlanBoardRaster.Day1;
                case '4':
                    return EPlanBoardRaster.Day2D5;
                case '5':
                    return EPlanBoardRaster.Day3D5;
                case '6':
                    return EPlanBoardRaster.Week1;
                case '7':
                    return EPlanBoardRaster.Month1;
            }
        }
    }
}
